import { ImageProcessor } from './imageProcessor.js';

export class DOMHandler {
    constructor() {
        this.imageProcessor = new ImageProcessor();
        this.clickedPoints = [];
        this.img = new Image();
        this.initializeElements();
        this.setupEventListeners();
    }

    initializeElements() {
        this.uploadButton = document.getElementById('uploadButton');
        this.originalCanvas = document.getElementById('originalCanvas');
        this.correctedCanvas = document.getElementById('correctedCanvas');
        this.highResCanvas = document.getElementById('highResCanvas');
        this.pointsContainer = document.getElementById('pointsContainer');
        this.instructions = document.getElementById('instructions');
        this.downloadButton = document.getElementById('downloadButton');
        this.resetPointsButton = document.getElementById('resetPoints');

        this.originalCtx = this.originalCanvas.getContext('2d');
        this.correctedCtx = this.correctedCanvas.getContext('2d');
    }

    setupEventListeners() {
        this.uploadButton.addEventListener('change', this.handleImageUpload.bind(this));
        this.originalCanvas.addEventListener('click', this.handleCanvasClick.bind(this));
        this.downloadButton.addEventListener('click', this.handleDownload.bind(this));
        this.resetPointsButton.addEventListener('click', (e) => {
            e.stopPropagation();
            this.resetPoints();
        });
    }

    handleImageUpload(event) {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = (e) => {
            this.img = new Image();
            this.img.onload = () => {
                const size = this.calculateDisplaySize(this.img.width, this.img.height);
                this.updateCanvasSize(size);
                this.drawOriginalImage(size);
                this.resetPoints();
            };
            this.img.src = e.target.result;
        };
        reader.readAsDataURL(file);
    }

    handleCanvasClick(event) {
        if (!this.img.src || this.clickedPoints.length >= 4) return;

        const point = this.calculateClickPoint(event);
        this.clickedPoints.push(point);
        this.drawPoint(point);

        if (this.clickedPoints.length === 4) {
            this.performImageCorrection();
        }
    }

    handleDownload() {
        try {
            const link = document.createElement('a');
            link.download = '矫正后的图片.png';
            link.href = this.highResCanvas.toDataURL('image/png', 1.0);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        } catch (error) {
            alert('下载图片时出错：' + error.message);
        }
    }

    calculateDisplaySize(width, height) {
        const maxWidth = 500;
        const maxHeight = 400;
        
        if (width > maxWidth || height > maxHeight) {
            const ratio = Math.min(maxWidth / width, maxHeight / height);
            width = Math.floor(width * ratio);
            height = Math.floor(height * ratio);
        }
        
        return { width, height };
    }

    updateCanvasSize(size) {
        this.originalCanvas.width = size.width;
        this.originalCanvas.height = size.height;
        this.correctedCanvas.width = size.width;
        this.correctedCanvas.height = size.height;
    }

    drawOriginalImage(size) {
        this.originalCtx.clearRect(0, 0, size.width, size.height);
        this.originalCtx.drawImage(this.img, 0, 0, size.width, size.height);
    }

    resetPoints() {
        if (!this.img.src) return;
        
        this.clickedPoints = [];
        this.pointsContainer.innerHTML = '';
        this.correctedCtx.clearRect(0, 0, this.correctedCanvas.width, this.correctedCanvas.height);
        this.instructions.textContent = '请点击图像的四个角点（顺序不限）';
        this.downloadButton.style.display = 'none';
    }

    calculateClickPoint(event) {
        const rect = this.originalCanvas.getBoundingClientRect();
        const scaleX = this.originalCanvas.width / rect.width;
        const scaleY = this.originalCanvas.height / rect.height;

        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;

        const boundedX = Math.max(0, Math.min(rect.width, x));
        const boundedY = Math.max(0, Math.min(rect.height, y));

        return {
            x: Math.round(boundedX * scaleX),
            y: Math.round(boundedY * scaleY)
        };
    }

    drawPoint(point) {
        const pointElement = document.createElement('div');
        pointElement.classList.add('point');
        const rect = this.originalCanvas.getBoundingClientRect();
        
        const scaleX = rect.width / this.originalCanvas.width;
        const scaleY = rect.height / this.originalCanvas.height;
        
        const exactX = point.x * scaleX;
        const exactY = point.y * scaleY;
        
        pointElement.style.left = `${exactX}px`;
        pointElement.style.top = `${exactY}px`;
        
        const label = document.createElement('div');
        label.classList.add('point-label');
        label.textContent = (this.clickedPoints.length).toString();
        
        pointElement.appendChild(label);
        this.pointsContainer.appendChild(pointElement);
    }

    async performImageCorrection() {
        try {
            this.instructions.textContent = '正在矫正图像...';
            
            const sortedPoints = this.sortPoints(this.clickedPoints);
            const outputSize = this.imageProcessor.calculateOutputSize(
                sortedPoints,
                this.img.width,
                this.img.height,
                this.originalCanvas.width,
                this.originalCanvas.height
            );
            
            const displaySize = this.calculateDisplaySize(outputSize.width, outputSize.height);
            
            // 设置画布尺寸
            this.correctedCanvas.width = displaySize.width;
            this.correctedCanvas.height = displaySize.height;
            this.highResCanvas.width = outputSize.width;
            this.highResCanvas.height = outputSize.height;

            // 计算源点和目标点
            const srcPoints = sortedPoints.map(p => [
                p.x * (this.img.width / this.originalCanvas.width),
                p.y * (this.img.height / this.originalCanvas.height)
            ]);
            
            const dstPoints = [
                [0, 0],
                [outputSize.width, 0],
                [outputSize.width, outputSize.height],
                [0, outputSize.height]
            ];

            // 执行图像矫正
            const correctedCanvas = this.imageProcessor.correctImage(
                srcPoints,
                dstPoints,
                this.img,
                outputSize.width,
                outputSize.height
            );

            // 更新显示
            this.highResCanvas.width = correctedCanvas.width;
            this.highResCanvas.height = correctedCanvas.height;
            const highResCtx = this.highResCanvas.getContext('2d');
            highResCtx.drawImage(correctedCanvas, 0, 0);

            // 缩放显示
            this.correctedCtx.drawImage(
                correctedCanvas,
                0, 0,
                displaySize.width,
                displaySize.height
            );

            this.instructions.textContent = '图像矫正完成。';
            this.downloadButton.style.display = 'inline-block';
        } catch (error) {
            alert('图像矫正失败：' + error.message);
            this.resetState();
        }
    }

    sortPoints(points) {
        // 计算边界框
        const minX = Math.min(...points.map(p => p.x));
        const maxX = Math.max(...points.map(p => p.x));
        const minY = Math.min(...points.map(p => p.y));
        const maxY = Math.max(...points.map(p => p.y));
        
        // 计算中心点
        const centerX = (minX + maxX) / 2;
        const centerY = (minY + maxY) / 2;

        // 对点进行分类
        const sortedPoints = points.map(p => ({
            ...p,
            // 计算点到中心的相对位置
            relX: p.x - centerX,
            relY: p.y - centerY
        }));

        // 找到四个角点
        const leftTop = sortedPoints.reduce((min, p) => 
            (p.relX <= 0 && p.relY <= 0 && 
            (p.relX * p.relX + p.relY * p.relY > min.relX * min.relX + min.relY * min.relY)) ? p : min, 
            sortedPoints.find(p => p.relX <= 0 && p.relY <= 0));

        const rightTop = sortedPoints.reduce((min, p) => 
            (p.relX > 0 && p.relY <= 0 && 
            (p.relX * p.relX + p.relY * p.relY > min.relX * min.relX + min.relY * min.relY)) ? p : min, 
            sortedPoints.find(p => p.relX > 0 && p.relY <= 0));

        const rightBottom = sortedPoints.reduce((min, p) => 
            (p.relX > 0 && p.relY > 0 && 
            (p.relX * p.relX + p.relY * p.relY > min.relX * min.relX + min.relY * min.relY)) ? p : min, 
            sortedPoints.find(p => p.relX > 0 && p.relY > 0));

        const leftBottom = sortedPoints.reduce((min, p) => 
            (p.relX <= 0 && p.relY > 0 && 
            (p.relX * p.relX + p.relY * p.relY > min.relX * min.relX + min.relY * min.relY)) ? p : min, 
            sortedPoints.find(p => p.relX <= 0 && p.relY > 0));

        // 返回排序后的点（左上、右上、右下、左下）
        return [
            { x: leftTop.x, y: leftTop.y },
            { x: rightTop.x, y: rightTop.y },
            { x: rightBottom.x, y: rightBottom.y },
            { x: leftBottom.x, y: leftBottom.y }
        ];
    }
}